<template>
  <div ref="display"></div>
</template>

<script>
  import Vue from 'vue'
  import randomStr from '../../utils/randomstr.js'
  export default {
    props: {
      // code 指定为vue文件模板内容
      code: {
        type: String,
        default: ''
      }
    },
    data () {
      return {
        html: '',
        css: '',
        js: '',
        id: randomStr()
      }
    },
    watch: {
      code() {
        this.destroyCode()
        this.renderCode()
      }
    },
    mounted() {
      this.renderCode()
    },
    beforeDestroy() {
      this.destroyCode()
    },
    methods: {
      // 获取代码部分函数
      getSource (source, type) {
        const regex = new RegExp(`<${type}[^>]*>`)
        let openingTag = source.match(regex)
        if (!openingTag) return ''
        else openingTag = openingTag[0]
        return source.slice(source.indexOf(openingTag) + openingTag.length, source.lastIndexOf(`</${type}>`))
      },
      // 代码分割函数 - 从code中获取到各个部分的代码
      splitCode() {
        const script = this.getSource(this.code, 'script').replace(/export default/, 'return ')
        const css = this.getSource(this.code, 'style')
        const template = this.getSource(this.code, 'template')
        this.js = script
        this.css = css
        this.html = template
      },
      renderCode() {
        this.splitCode()
        if (this.html !== '' && this.js !== '') {
          // eslint-disable-next-line no-new-func
          const parseStrToFunc = new Function(this.js)()
          parseStrToFunc.template = this.html
          
          const Component = Vue.extend(parseStrToFunc)
          this.component = new Component().$mount()
          this.$refs.display.appendChild(this.component.$el)

          // 添加css
          if (this.css !== '') {
            const style = document.createElement('style')
            style.type = 'text/css'
            style.id = this.id
            style.innerHTML = this.css
            document.getElementsByTagName('head')[0].appendChild(style)
          }
        }
      },
      destroyCode() {
        // 移除css
        const $target = document.getElementById(this.id)
        if ($target) $target.parentNode.removeChild($target)

        // 移除组件
        if (this.component) {
          this.$refs.display.removeChild(this.component.$el)
          this.component.$destroy()
          this.component = null
        }
      }
    }
  }
</script>
<style lang='scss' scoped>
</style>
